Fastify is a small Node framework for developing back end web apps.
In this article, we’ll look at how to create back end apps with Fastify.
Fluent Schema
We can set up a schema to validate request content with the fluent-schema
module in our Fastify app.
For example, we can write:
const fastify = require('fastify')({})
const S = require('fluent-schema')
const MY_KEYS = {
KEY1: 'ONE',
KEY2: 'TWO'
}
const bodyJsonSchema = S.object()
.prop('someKey', S.string())
.prop('someOtherKey', S.number())
.prop('requiredKey', S.array().maxItems(3).items(S.integer()).required())
.prop('nullableKey', S.mixed([S.TYPES.NUMBER, S.TYPES.NULL]))
.prop('multipleTypesKey', S.mixed([S.TYPES.BOOLEAN, S.TYPES.NUMBER]))
.prop('multipleRestrictedTypesKey', S.oneOf([S.string().maxLength(5), S.number().minimum(10)]))
.prop('enumKey', S.enum(Object.values(MY_KEYS)))
.prop('notTypeKey', S.not(S.array()))
const queryStringJsonSchema = S.object()
.prop('name', S.string())
.prop('excitement', S.integer())
const paramsJsonSchema = S.object()
.prop('par1', S.string())
.prop('par2', S.integer())
const headersJsonSchema = S.object()
.prop('x-foo', S.string().required())
const schema = {
body: bodyJsonSchema,
querystring: queryStringJsonSchema,
params: paramsJsonSchema,
headers: headersJsonSchema
}
fastify.post('/', { schema }, function (req, reply) {
reply.send('success')
})
const start = async () => {
try {
await fastify.listen(3000, '0.0.0.0')
} catch (err) {
fastify.log.error(err)
process.exit(1)
}
}
start()
We add the bodyJsonSchema
to validate the request body.
S.object
is called to let us validate objects.
prop
is used to validate properties. It takes the property name as the first argument.
S.string
indicates that it’s a string.
S.array
validates that a property is an array.
maxItems
validates the max number of items in an array.
S.oneOf
lets us specify one of multiple types for a property.
S.enum
validates a property is an enum. It takes a string array with the enum values.
We can also specify validation schemas for query strings, URL parameters, and headers with fluent-schema
.
Now when we make a request with content that doesn’t match the schema, we’ll get an error.
Schema Reuse
We can reuse our schemas by adding an ID to them with the id
method.
For instance, we can write:
const fastify = require('fastify')({})
const S = require('fluent-schema')
const addressSchema = S.object()
.id('#address')
.prop('line1').required()
.prop('line2')
.prop('country').required()
.prop('city').required()
.prop('zip').required()
const commonSchemas = S.object()
.id('app')
.definition('addressSchema', addressSchema)
fastify.addSchema(commonSchemas)
const bodyJsonSchema = S.object()
.prop('home', S.ref('app#address')).required()
.prop('office', S.ref('app#/definitions/addressSchema')).required()
const schema = { body: bodyJsonSchema }
fastify.post('/', { schema }, function (req, reply) {
reply.send('success')
})
const start = async () => {
try {
await fastify.listen(3000, '0.0.0.0')
} catch (err) {
fastify.log.error(err)
process.exit(1)
}
}
start()
to create our schemas with the addressSchema
.
Then we add the definition to a reusable schema with the definition
method.
id
specifies the ID of the schema.
S.ref
lets us reference a schema in the code by its ID so we can reuse them.
Then we create the schema
object and pass it to the 2nd argument of post
.
We can also create the schema with an object:
const fastify = require('fastify')({})
const sharedAddressSchema = {
$id: 'sharedAddress',
type: 'object',
required: ['line1', 'country', 'city', 'zip'],
properties: {
line1: { type: 'string' },
line2: { type: 'string' },
country: { type: 'string' },
city: { type: 'string' },
zip: { type: 'string' }
}
}
fastify.addSchema(sharedAddressSchema)
const bodyJsonSchema = {
type: 'object',
properties: {
vacation: 'sharedAddress#'
}
}
const schema = { body: bodyJsonSchema }
fastify.post('/', { schema }, function(req, reply) {
reply.send('success')
})
const start = async () => {
try {
await fastify.listen(3000, '0.0.0.0')
} catch (err) {
fastify.log.error(err)
process.exit(1)
}
}
start()
We create an object for the schema.
Then we all fastify.addSchema
to add the schema.
And then we create the schema
object with the added schema which references the schema by the $id
property.
And then we add the schema
to the route handler.
Conclusion
We can add validation for requests with the fluent-schema
library to our Fastify app.